Febrary 2019
修正箇所にハイライト(OR 取り消し線)を引いてコメントを書ける.
version管理ができない問題は解決
最も有名なversion管理ツール -> Git
Gitに加えてGithubのIssue,Pull request(PR)のレビュー機能を用いることで, コメントを本文に反映するのが面倒問題と生のtexが見れない問題も解決
さらにTODOを管理するIssueを使うことで,楽にタスクを振れる(振られた側もGoalが明確に示されるため楽)
もちろん,原稿執筆だけでなく,ソースコードやVimの設定ファイルとかの管理にも使える.
Git使おう.
ちゃんと勉強してから使おう.
2と3をひたすら繰り返す.
重犯罪人に自分の罪を思い知らせるなら、土を掘り移動させ、それからまた埋めて元に戻す、という作業を延々と繰り返させればよい。それは究極の拷問であり、最後には精神に異常をきたすであろう。(ドフトエフスキー?)
revesion管理基礎
分岐する場合を扱う
Cloudを利用
プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムだよ.

リーナス・トーバルズ
よくない.
Google driveでできないこと
この2つの欠点のせいで,シミュレータが動く状態のdirectoryに戻したいとかいうことができない.
自動的(Automatic)はユーザから選択の自由を奪っている.
オートマ => 人権侵害
恣意的な表
| 機能 | Adobe reader | Google Drive | Git + Github |
|---|---|---|---|
| 保存 | × | ○ | ○ |
| 保存するタイミングの制御 | × | × | ○ |
| ファイル選択して保存 | × | × | ○ |
| 復元 | × | ○ | ○ |
| 分岐 | × | × | ○ |
| 差分の表示 | × | × | ○ |
| 履歴の一元管理 | × | ○ | ○ |
Gitには3つの視点がある
これらを理解すればGit master.
Commit (directoryのスナップショット)からなるツリー(一番重要).


1つのCommitの裏には3つのレイヤがある

もう少しわかりやすく
fileには4つの状態がある(three areasと合わせて覚えると良い)

あなたは,gitマスターになりました.
異世界に行ったら最初に唱える呪文.
File statusが4つのどの状態にあるかの確認.
# 準備 cd path/to/workspace mkdir repo000 cd repo000
git status
これから何かする度になるべくgit statusしましょう.

current directoryにgit repositoryを作る
git init
current directoryからgit repositoryを削除する ! 削除したrepositoryは元に戻せないので注意
rm -R .git
ファイルをStaged areaに追加する.
git add [path ...]
echo "ROW000" > file000 git add file000
git reset [--soft | --hard] [<commit>] [path ...]
git reset HEAD file000
stage(git add)されたすべてのファイルを対象にしたい場合
git reset HEAD
staged(git add)されたすべてのファイルのコピーをGit Directoryへ記録する
# 準備 git add file000
git commit [--amend] [-m <msg>]
git commit -m "Added file000."
Git Directoryから最後のCommitを削除する
# 準備 cp file000 file001 git add file001 git commit -m "Added file001."
git reset --soft HEAD^ # HEAD^ = 1つ前の親Commit
addもなかったことに
# 復習 git reset HEAD
commitとaddの2つをまとめてなかったことに
git reset HEAD^
$ git reflog
e170b24 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
953913d HEAD@{1}: commit: Added file001. <-- resetするまえのHEADの位置
...
git reset HEAD@{1} # HEAD@{1} = 1つ前にHEADの指していたcommit
| HEAD | インデックス | 作業ディレクトリ | 作業ディレクトリ保護の有無 | |
|---|---|---|---|---|
|
Commit Level |
||||
|
|
REF |
いいえ |
いいえ |
はい |
|
|
REF |
はい |
いいえ |
はい |
|
|
REF |
はい |
はい |
いいえ |
|
|
HEAD |
はい |
はい |
はい |
|
File Level |
||||
|
|
いいえ |
はい |
いいえ |
はい |
|
|
いいえ |
はい |
はい |
いいえ |
つまり?
git reset --hard, git checkout <file> (上表で太字のいいえになっているやつ) するときは気をつけよう.
ファイルをStaged areaとGit directoryから削除する
(=untracked(gitの追跡対象外)にする)
git rm [--cached] [path ...]
cd path/to/workspace mkdir repo002 cd repo002 git init echo "ROW000" > file000 git add file000 git commit -m "Added file000."
# 復習 git add file000 # tracked(gitの追跡対象指定)にする
git rm --cached file000
一生untrackedにしておきたいfileやdirectoryは,.gitignoreというfileを作ってそこに書く.
.gitignoreしたdirectory内の一部のfileのみをtrackedにしたい場合は,.gitkeepに書いてignoreされないようにする.
.gitignore(.gitkeep)については,自分でググってね. (i.e., あまり興味ない)

ファイルをWorking Directory, Staged area, Git directoryのすべてから削除する.
# 準備 git add file000
rm file000 git add file000 # git rm --cached file000でも良い git commit -m "Removed file000."
上の2つをまとめてやる
# 準備 git reset --hard HEAD^ # HEAD^ = 1つ前の親Commit
git rm file000 git commit -m "Removed file000."
ファイルをWorking Directory, Staged area, Git directoryのすべてにおいてmoveまたはrenameする.
Note: mvとrenameは本質的に同じ
git mv <source> <destination>
# 準備 git reset --hard HEAD^
git mv file000 file001 git commit -m "Renamed file000 to file001."
最後のCommitを変更する
# 準備 cd path/to/workspace mkdir repo003 git init echo "ROW000" > file000 cp file000 file001 git add file000 git commit -m "Added file000."
ファイルをaddし忘れたときとか,コメントを修正したい時とかに便利
git add file001 git commit --amend -m "Added file000 and file001."
直前だけじゃなく,もっと前まで遡って自分の都合の良いように歴史を改変したい
git rebase -i <commit>
<commit>からHEADまでのコミットをまとめて変更する
# 準備 rm -rf * echo "ROW000" > file000 git commit -a -m "Added file000." for f in file001 file002 file003 gomi; do cp file000 $f; done # file001, file002, file003, gomiができれば何でも良い git add file001 git commit -m 'Added file001.' git add file002 git commit -m 'Added file002.' git add file003 git commit -m '「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される' git add gomi git commit -m 'Added gomi.'
git rebase -i <commit>
* bf1b31a (HEAD -> master) Added gomi. # * fb7cc7b 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # <-- HEAD~1 or HEAD^ * 469a642 Added file002. # <-- HEAD~2 or HEAD^^ * f8c8773 Added file001. # <-- HEAD~3 or HEAD^^^ * 2312317 Added file000. # <-- HEAD~4 or HEAD^^^^
<commit>には変更の根本となるcommitを指定する.
git rebase -i HEAD~4 # HEAD~4 = 4つ前の親Commit
この場合変更対象はHEAD - HEAD~3
pick 17b9da7 Added file001. pick 98ee317 Added file002. pick 9a7d9db 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される pick 00805cf Added gomi. # Rebase e170b24..00805cf onto e170b24 (4 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
1番目と2番目はまとめたくて,3番目のメッセージを書き直したくて,4番目は消したい.
pick 17b9da7 Added file001. s 98ee317 Added file002. e 9a7d9db 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される d 00805cf Added gomi. # Rebase e170b24..00805cf onto e170b24 (4 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
# This is a combination of 2 commits. # This is the 1st commit message: Added file001. # This is the commit message #2: Added file002. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (2 commands done): # pick 5b6d77f Added file001. # squash 21c25a0 Added file002. # Next commands to do (2 remaining commands): # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # drop cf942f2 Added gomi. # You are currently rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file001 # new file: file002
# This is a combination of 2 commits. # This is the 1st commit message: Added file001 and file002. # This is the commit message #2: # Added file002. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (2 commands done): # pick 5b6d77f Added file001. # squash 21c25a0 Added file002. # Next commands to do (2 remaining commands): # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # drop cf942f2 Added gomi. # You are currently rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file001 # new file: file002
[detached HEAD 0136ee2] Added file001 and file002. Date: Sat Feb 16 22:50:41 2019 +0900 2 files changed, 2 insertions(+) create mode 100644 file001 create mode 100644 file002 Stopped at 2f734eb... 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される You can amend the commit now, with git commit --amend # <-- commitを編集したいのでまずは,こっち Once you are satisfied with your changes, run git rebase --continue
git logを見てみると<commit>で指定した根本から枝分かれしていることがわかる
$ git log --oneline --graph --all * 87449ac (HEAD) 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される * 2f98c92 Added file001 and file002. | * bf1b31a (master) Added gomi. | * fb7cc7b 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される | * 469a642 Added file002. | * f8c8773 Added file001. |/ * 2312317 Added file000.
git commit --amend
「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (3 commands done): # squash 21c25a0 Added file002. # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # Next command to do (1 remaining command): # drop cf942f2 Added gomi. # You are currently editing a commit while rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file003 #
Added file003. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (3 commands done): # squash 21c25a0 Added file002. # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # Next command to do (1 remaining command): # drop cf942f2 Added gomi. # You are currently editing a commit while rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file003 #
終わったらcontinue
git rebase --continue
rebaseの途中でやっぱりやめたくなった
git rebase --abort
rebaseしたあと,やっぱりなかったことにしたくなった
rebaseは既存のcommitをコピーを作っているだけなので,元のcommitも残っている(見えなくなっているだけ).
* 99d7024 (master) Added file003 * 2f98c92 Added file001 and file002. | * bf1b31a (HEAD) Added gomi. # <-- 元のHEAD | * fb7cc7b 再帰で検索して「もしかして:再帰」をクリックすると…。 | * 469a642 Added file002. | * f8c8773 Added file001. |/ * 2312317 Added file000.
見えないcommitをたどるにはreflog.
$ git reflog
a264b19 (HEAD -> master) HEAD@{0}: rebase -i (finish): returning to refs/heads/master
a264b19 (HEAD -> master) HEAD@{1}: commit (amend): Added file003.
ecc3571 HEAD@{2}: rebase -i (edit): 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される
9070db1 HEAD@{3}: rebase -i (squash): Added file001 and file002.
408797f HEAD@{4}: rebase -i (start): checkout HEAD~4
92b7c29 HEAD@{5}: commit: Added gomi. # <-- rebase前のHEADの位置
...
git reset --hard HEAD@{5} # HEAD@{5} = 5つ前にHEADの指していたcommit
$ git reflog
92b7c29 (HEAD -> master) HEAD@{0}: reset: moving to HEAD@{5} # <-- さっきのreset
a264b19 (HEAD -> master) HEAD@{1}: rebase -i (finish): returning to refs/heads/master
a264b19 (HEAD -> master) HEAD@{2}: commit (amend): Added file003.
ecc3571 HEAD@{3}: rebase -i (edit): 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される
9070db1 HEAD@{4}: rebase -i (squash): Added file001 and file002.
408797f HEAD@{5}: rebase -i (start): checkout HEAD~4
92b7c29 HEAD@{6}: commit: Added gomi.
...
git reset --hard HEAD@{1}
基本の呪文 Commit treeを表示する
git log --oneline --graph --all
defaultのgit logは見にくいので,いい感じで表示してくれるwrapperもある.
$ git-foresta --all | less -RSX
99d7024c 2019-02-19 10:31 ○ ameono (master) Added file003
2f98c925 2019-02-19 10:31 ● ameono Added file001 and file002.
bf1b31ad 2019-02-19 10:31 │ ○ ameono (HEAD) Added gomi.
fb7cc7b0 2019-02-19 10:31 │ ● ameono 再帰で検索して「もしかして:再帰」をクリックすると…。
469a6426 2019-02-19 10:31 │ ● ameono Added file002.
f8c8773e 2019-02-19 10:31 │ ● ameono Added file001.
├─┘
2312317f 2019-02-19 10:30 ■ ameono Added file000.
Commit (directoryのスナップショット)からなるツリー.

# 準備 cd path/to/workspace mkdir repo005 cd repo005 git init echo "ROW000" > file000 git add file000 git commit -m "Added file000."
git branch [-d|-D] <branch-name> [<start-point>]
git branch feature/update_file000 master
feature/branch000という名前のrefを作る(指す先はmasterの指しているところ)
branchを削除する.
git branch -d feature/update_file000
未mergeのbranchは削除しようとするエラーが出る(二度と見つけられなくなるため)ので強制削除する必要がある.
強制的に削除する場合.
git branch -D feature/update_file000
$ git branch -d feature/update_file000 Deleted branch feature/update_file000 (was e170b24). # <-- ここのhashを覚えておく
git checkout e170b24 git checkout -b feature/update_file000
HEADの指す先を
git checkout [-b] [<branch>|<commit>]
git checkout feature/update_file000
HEADの指す先をfeature/branch000へ変える
branchの作成とcheckoutをいっぺんにやる
git checkout -b feature/update_file000
git branch testing

git checkout testing

CLIで見てみる
$ git branch feature/update_file000
$ git log --graph --all
* commit e170b24890ca2685d9414b15f3862a28b16b3828 (HEAD -> master, feature/branch000)
Author: ameono <4m3on0@gmail.com>
Date: Sat Feb 16 21:28:33 2019 +0900
Added file000.
$ git checkout feature/update_file000
$ git log --graph --all
* commit e170b24890ca2685d9414b15f3862a28b16b3828 (HEAD -> feature/branch000, master)
Author: ameono <4m3on0@gmail.com>
Date: Sat Feb 16 21:28:33 2019 +0900
Added file000.
HEAD -> の指す先に注目.
echo "ROW001" >> file000 git add file000 git commit -m "Updated file000 (added the second row)."
masterと違うCommitを指していることを確認
git log --oneline --graph --all
git checkout master cat file000 # update_file000ブランチの変更が反映されていないことを確認 cp file000 file001 git add file001 git commit -m "Added file001."
分岐したことを確認
git log --oneline --graph --all
他のbranchの先端と今のbranchの先端を統合するcommitを作る
git merge [<branch>]
MergeといえばPR.
GithubでPRをmergeするときはこんな感じのことをしている.
git checkout feature/update_file000 git merge master
$ git log --oneline --graph --all * 0b45d32 (HEAD -> feature/update_file000) Merge branch 'master' into feature/update_file000 |\ | * 179a3bc (master) Added file001. * | cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
Merge commitができている.
git checkout master git merge --no-ff feature/update_file000
$ git log --oneline --graph --all * 500adbb (HEAD -> master) Merge branch 'feature/update_file000' |\ | * 0b45d32 (feature/update_file000) Merge branch 'master' into feature/update_file000 | |\ | |/ |/| * | 179a3bc Added file001. | * cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
Merge commitがまたできている.
$ git log --oneline --graph --all * 500adbb (HEAD -> master) Merge branch 'feature/update_file000' |\ | * 0b45d32 (feature/update_file000) Merge branch 'master' into feature/update_file000 | |\ | |/ |/| * | 179a3bc Added file001. # <-- Merge前のmaterの位置 | * cf7cb13 Updated file000 (added the second row). # <-- Merge前のfeature/update_file000の位置 |/ * e170b24 Added file000.
master tagとupdate_file000 tagをそれぞれMerge前の位置に戻せば良い.
(復習) HEAD^ = 1つ前の親Commit
親が2つ以上ある場合 HEAD^N (N=親の番号) のように指定できる.
$ git show --name-only HEAD^
commit 179a3bce92c28cb9a6ac1ef4d8ff4002c83d2f7d
Author: ameono <4m3on0@gmail.com>
Date: Sun Feb 17 00:57:33 2019 +0900
Added file001.
$ git show --name-only HEAD^2
commit 0b45d32e5332152a5a44400d6394344199f4f968 (feature/update_file000)
Merge: cf7cb13 179a3bc
Author: ameono <4m3on0@gmail.com>
Date: Sun Feb 17 14:51:11 2019 +0900
Merge branch 'master' into feature/update_file000
HEAD~2と似てるけど,全然意味が違う.
$ git show --name-only HEAD~2
commit e170b24890ca2685d9414b15f3862a28b16b3828
Author: ameono <4m3on0@gmail.com>
Date: Sat Feb 16 21:28:33 2019 +0900
Added file000.

HEAD~N = HEADのN個前の親Commit
HEAD^N = HEADの1個前の親CommitのN番目
ex) 1個前の親の2番めの親Commit = HEAD~1^2
masterのMergeをなかったことに
git reset --hard HEAD^
$ git log --oneline --graph --all * 0b45d32 (feature/update_file000) Merge branch 'master' into feature/update_file000 |\ | * 179a3bc (HEAD -> master) Added file001. * | cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
update_file000のMergeをなかったことに
git checkout feature/update_file000 git reset --hard HEAD^
$ git log --oneline --graph --all * 179a3bc (master) Added file001. | * cf7cb13 (HEAD -> feature/update_file000) Updated file000 (added the second row). |/ * e170b24 Added file000.
簡単ですね?
今までの話が理解できていれば,mergeをなかったことにしたのをなかったことにもできるはず.
(復習) git checkout feature/update_file000 git merge master git checkout master git merge --no-ff feature/update_file000 <-- --no-ffに注目
no-ff = No Fast Forward
なしにしてやってみる
git checkout feature/update_file000 git merge master git checkout master git merge feature/update_file000
$ git log --oneline --graph --all * e6de5fd (HEAD -> master, feature/update_file000) Merge branch 'master' into feature/update_file000 |\ | * 179a3bc Added file001. * | cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
git rebase [<branch>]
git rebase --continue | --skip | --abort | --quit |
他のbranchの先端に今のbranchの根本から先端までのcommitをまとめて移植する
# 準備 git branch -f feature/update_file000 HEAD^2 git reset --hard HEAD^ git checkout feature/update_file000
git rebase master
$ git log --oneline --graph --all * a336ea3 (HEAD -> feature/update_file000) Added file001. * cf7cb13 (master) Updated file000 (added the second row). * e170b24 Added file000.
$ git rebase feature/update_file000 First, rewinding head to replay your work on top of it... Fast-forwarded master to feature/update_file000. $ git log --oneline --graph --all * a336ea3 (HEAD -> master, feature/update_file000) Added file001. * cf7cb13 Updated file000 (added the second row). * e170b24 Added file000.
まずはmasterを戻す.
$ git reset --hard HEAD^ * a336ea3 (feature/update_file000) Added file001. * cf7cb13 (HEAD -> master) Updated file000 (added the second row). * e170b24 Added file000.
次にupdate_file000を戻す
$ git reflog
a336ea3 (HEAD -> feature/update_file000) HEAD@{2}: checkout: moving from master to feature/update_file000
cf7cb13 (master) HEAD@{3}: reset: moving to HEAD^
a336ea3 (HEAD -> feature/update_file000) HEAD@{4}: rebase finished: returning to refs/heads/master
a336ea3 (HEAD -> feature/update_file000) HEAD@{5}: rebase: checkout feature/update_file000
cf7cb13 (master) HEAD@{6}: checkout: moving from feature/update_file000 to master
a336ea3 (HEAD -> feature/update_file000) HEAD@{7}: rebase finished: returning to refs/heads/feature/update_file000
a336ea3 (HEAD -> feature/update_file000) HEAD@{8}: rebase: Added file001.
cf7cb13 (master) HEAD@{9}: rebase: checkout master
179a3bc HEAD@{10}: checkout: moving from master to feature/update_file000 # <-- これ
$ git reset --hard HEAD@{10}
$ git log --oneline --graph --all
* 179a3bc (HEAD -> feature/update_file000) Added file001.
| * cf7cb13 (master) Updated file000 (added the second row).
|/
* e170b24 Added file000.
Mergeより戻すのが面倒(reflog使わないかん)ですね.
このことから,rebaseとmergeならmergeを使うべきという人もいます.
公式曰く,
公開リポジトリにプッシュしたコミットをリベースしてはいけない
この指針に従っている限り、すべてはうまく進みます。もしこれを守らなければ、あなたは嫌われ者となり、友人や家族からも軽蔑されることになるでしょう。(Pro Git)
歴史改変のrebase(左)とbranchのrebase(右) やっていることは同じ.
git cherry-pick <commit>...
他のbranchの特定のcommitを今のbranchの先端に移植する
$ git log --oneline --graph --all * 179a3bc (HEAD -> feature/update_file000) Added file001. | * cf7cb13 (master) Updated file000 (added the second row). |/ * e170b24 Added file000.
$ git cherry-pick cf7cb13
$ git log --oneline --graph --all * 8a1eae4 (HEAD -> feature/update_file000) Updated file000 (added the second row). * 179a3bc Added file001. | * cf7cb13 (master) Updated file000 (added the second row). |/ * e170b24 Added file000.
masterのcommitがfeature/update_file000へcopyされた
rebaseはcherry-pickを複数まとめてやっているだけとも言える.
# 準備 git reset --hard HEAD^ echo "ROW002 <- update_file000" >> file000
$ git merge master Auto-merging file000 CONFLICT (content): Merge conflict in file000 Automatic merge failed; fix conflicts and then commit the result.
ROW000 <<<<<<< HEAD ROW002 <- update_file000 ======= ROW001 >>>>>>> master
git checkout [--theirs|--ours] <paths> を使うそのまんま. Vimとかでひらいて↓こんな感じに編集して保存,AddしてCommit
ROW000 ROW002 <- update_file000
git checkout --theirs file000
ROW000 <<<<<<< HEAD # = --ours ROW002 <- update_file000 ======= ROW001 >>>>>>> master # = --theris
merge元のbranch(=–theirs)の変更かmerge先(=HEAD, –ours)の変更かのどちらかを採用する.
利点: pdfや画像などテキストとして編集できないものがConflictしたときに便利
PDFをVimで開いて「この行はmerge先を採用して,こっちはbranchを採用…」とかやってるやつがいたら病気…
欠点: どういう結果になるか予想がつきにくい.
merge-toolには色々ある.
git mergetool --tool=vimdiff
DiffがあるChunk(=色が変わっている部分)にカーソルを合わせ, 1do, 2do, 3doと入力することで,それぞれ上段の左から1番目,2番目,3番目が今後の姿に取り込まれる.
PyCharmのようにConflictを解消するツールが付いているIDEもある.

GitHub は世界最大の Remote Git リポジトリホスティングサービスだよ.
つまり?
localのrepository = localのPCにおいてあるdirecotry
とすると,
Github上のrepository = Google driveにおいてあるdirecotry
のような関係.
有名どころ
Github
Gitlab
Bitbucket
Githubがやたら有名だが他にもある (Google driveとDropbox的な関係).
できることは大差ないので,お財布事情とUIの好みの問題
(あとは狸と猫のどっちが好きかとか…バケツ…).

とにかく有名 (連携サービスが多いイメージ).
お金たくさん持ってく.
Github Educationとか言う学生プランに加入するとGithub含め色々な有名サービスが無料で使える.
本田圭佑がいる
他の2つと違い自前のCIとかはない(他のツールと組み合わせる前提OSSの思想的には○?)
どちらかというと,自組織のサーバにインストールして自分たちしかアクセスできないRemote repositoryとして使う (要するに自前のfile server的なやつ)オンプレミス版のほうが有名.
Slackを水で薄めたようなchatアプリやCIがついてくるので,これひとつで開発に必要なすべての作業を完結させることができる.
大人の事情でPublic臭の強いGithubとかSlackとかを使えない人たちが使ってるっぽい(NASAとか).
一昔前までPrivate repository(外部公開されない) 作り放題な唯一のサービスだったので,個人の利用者が多くいた(今は,Githubも作り放題).
Source treeの開発元でもあるAtlassianの製品.
お金ないらしい(最近値上げした).
https://stackshare.io/stackups/bitbucket-vs-github-vs-gitlab
2019 2月現在,各サービスの無料プランの状況
| Github | Bitbucket | Github (学生) | Bitbucket (学生) | GitLab | |
|---|---|---|---|---|---|
| private repository | 無制限 | 無制限 | 無制限 | 無制限 | 無制限 |
| public repository | 無制限 | 無制限 | 無制限 | 無制限 | 無制限 |
| collaborator | 3名まで | 5名まで | 無制限 | 無制限 | 無制限 |
| CI build time | - | 50分/月 | - | 500分/月 | 2000分/月 |
| LFS | 1GB | 1GB | 1GB | 5GB | 無制限? |
| LFS Bandwidth | 1GB/月 | 無制限 | 1GB/月 | 無制限 | 無制限? |
remote repositoryのcopyをlocalに作る.(= Download)
git clone <repository>
最初の一回しか使わない(あとはpullやfetch).
現在のremoteの<branch> refsの位置に合わせてlocalのorigin/<branch> refsの位置を更新する.
git fetch <remote> <branch>
このままではremoteのmaster(origin/master)がlocalのmasterに反映されていないので,masterをorigin/masterにmergeする.
git merge origin/master
remote branchの変更をlocalのbranchに取り込む (Downloadに近い)
git pull [--rebase|--no-ff] <remote> <branch>
git fetch と git merge origin/master をまとめてやる(--rebaseつけるとgit rebase origin/masterになる)
Mergeの作業が入っているため,pullではConflictが発生する可能性がある.
PRという名前はGithubのPRのMergeにpull(fetch+merge)コマンドが含まれることに由来する
local branchの変更をremote branchに反映させる (Uploadに近い)
git push <remote> <branch>
git pullのremoteとlocalを逆にしたもの(pullと違いConflictする場合は実行できない= –ff-only).
何れかの原因でConflictする場合,pushはできないので適切な方法で対処する
git push -f <remote> <branch>, git push --force-with-lease <remote> <branch> で強制pushするgit push -f は強制的にremoteを上書きするので,ミスるとremoteからすべての歴史を吹き飛ばすので(頭真っ白になる), 吹き飛ばしても人に迷惑のかからないfeature branchのみで使うこと.
--force-with-lease オプションはローカルのrefsがremoteと一致している場合のみ(i.e., localが最新の場合)強制的にremoteを上書きするのでやや安全
git pull <remote> <branch> してConflictを解消してからpushする (pullはconflictが起こっても実行できるため)最新のmasterにfeatureをrebaseしたい場合の例
# pull version (HEAD -> feature) git checkout master git pull origin master git checkout feature git rebase master
# fetch version (HEAD -> feature) git fetch origin git rebase origin/master
は?
特に,HEADに未commitのfileがあるときにこれをやりたくなるとpullでは非常に面倒(stashを使えばいいのだが更に2コマンド増える)
branchをどのように切るか(branch戦略)を決めるstyleの一つ.
別に守らなくてもErrorは起きないが,守ると便利なルール(Coding styleとかと同じ立ち位置).

featureとmasterしかないシンプルなFlow.
面倒なことはPR上でやる.
正解はないので,その都度最適な戦略を考えて選択するべきだが,一例として以下のようなものを提案しておく.
1つの研究の原稿は同じRepositoryで管理し,研究会->国際会議->修論などのようにVersionアップするたびにreleaseしていくといいんじゃない?
cloneするのにすごく時間がかかるようになります.
やっちゃったらGitの内側 - メインテナンスとデータリカバリを参考に当該のファイルを削除する(失敗するとCommitツリーを破壊するリスクがあるのでしないにこしたことはない)
Tips: Git LFS という大容量バイナリファイルを扱う方法も提供されている
featureでdevelopやmasterをrebaseするのはおk
git push -fするGithubでは,push -fできないようにbranchをprotectすることも可
やってしまっても大概なんとかなるけど,他の人にすごく迷惑がかかるので,喧嘩売りたいとき以外はやめましょう.
何かしようと思ったらとりあえずIssue起てる.
Added some files. #1 のようにすると1番のIssueのページから当該のCommitが見れるようになりトラッキングが楽.
よいPRには,LGTM (Looks Good To Me) を送りましょう.


git clone https://github.com/h1r0mu/git-tutorial.gitgit branch feature/issue番号-自分の名前 とかでbranchを切ってcheckoutslide/body/内に自分の名前.mdを作って,Markdownのリストで自己紹介文を書くAdded a self-introduction slide. #<Issue番号>のようにする- リスト1
- ネスト リスト1_1
- ネスト リスト1_1_1
- ネスト リスト1_1_2
- ネスト リスト1_2
- リスト2
- リスト3
特に以下の3つのコマンド(keyword)については一読しておいたほうが良い.
/* # 最初のコミット */
/* # ブロックチェーンとGit */
/* # Gitの名前の由来 */